package controller;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import parsers.AlimentoParser;

import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.stmt.PreparedQuery;

import dtos.AlimentoDTO;
import android.content.Context;
import DB.DatabaseHelper;
import model.Alimento;
import model.AlimentoCategoria;
import model.Consumo;

public class AlimentoController {
	private static AlimentoController instance = null;
	protected AlimentoController() {
	}
	public static AlimentoController getInstance() {
		if(instance == null) {
    	  instance = new AlimentoController();
		}
		return instance;
	}
	public void index(){
		
	}
	public void add(){
		
	}
	public void update(){
			
		}
	public void delete(){
		
	}
	public Alimento obtenerAlimentoLazy(int id, Context context){
		DatabaseHelper db =new DatabaseHelper(context);
		try {
			Dao<Alimento, Integer> alimentoDao = db.getAlimentoDao();
			Alimento alimento=alimentoDao.queryForId(id);
			if(alimento!=null){
				return alimento;
			}
			else{
				return null;
			}
		} 
		catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	
	}
	public ArrayList<AlimentoDTO> obtenerAlimentos(Context context) {
		DatabaseHelper db =new DatabaseHelper(context);
		ArrayList<Alimento> alimentos=null;
		try {
			List<Integer>ids=new ArrayList<Integer>();
			Dao<Alimento, Integer> alimentoDao = db.getAlimentoDao();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");      
			Date hoy = sdf.parse(sdf.format(new Date()));
			GenericRawResults<String[]> rawResults = alimentoDao.queryRaw("select * from consumos where "+ Consumo.FECHA_CONSUMO_FIELD_NAME +" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000)));
			List<String[]> results = rawResults.getResults();
			//Veo si existen consumos del dia la fecha
			if(!results.isEmpty()){
				rawResults = alimentoDao.queryRaw("select alimento_nutriente.id_alimento "
																			+ "from (select regimen.nutriente_id,regimen.nombre,cantidad-consumido as cantConsu "
																			+ "from (select nutriente_id,nutrientes.nombre,compuestos.cantidad from (select * from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen_alimenticio "
																			+ "inner join compuestos on compuestos.regimen_alimenticio_id=regimen_alimenticio.id "
																			+ "inner join nutrientes on nutrientes.id=compuestos.nutriente_id group by (compuestos.nutriente_id)) as regimen "
																			+ "inner join (select nutriente_id,nutrientes.nombre,sum(compuestos.cantidad * consumos.cantidad) as consumido from alimentos "
																			+ "inner join consumos on alimentos.id=consumos.alimento_id "
																			+ "inner join compuestos on compuestos.alimento_id=alimentos.id "
																			+ "inner join nutrientes on nutrientes.id=compuestos.nutriente_id where "+Consumo.FECHA_CONSUMO_FIELD_NAME+" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000))+" "
																			+ "group by (compuestos.nutriente_id)) as consumo on consumo.nutriente_id=regimen.nutriente_id) as puedo_consumir "
																			+ "inner join (select alimentos.id as id_alimento, nutriente_id, cantidad from alimentos "
																			+ "inner join compuestos on alimentos.id=compuestos.alimento_id  order by compuestos.alimento_id, compuestos.nutriente_id) alimento_nutriente on alimento_nutriente.nutriente_id=puedo_consumir.nutriente_id "
																			+ "where  puedo_consumir.cantConsu- alimento_nutriente.cantidad>0 "
																			+ "group by alimento_nutriente.id_alimento having count(*)>4");
		    	results = rawResults.getResults();
		    	if(!results.isEmpty()){
		    		
					for (String[] strings : results) {
						ids.add(Integer.parseInt(strings[0]));
					}
		    	}
		    	/*Siempre muestro los Libres, aunque se pasen, justamente porque son "Libres"*/
		    	Dao<AlimentoCategoria, Integer> alicatDao=db.getAlimentoCategoriaDao();
		    	PreparedQuery<AlimentoCategoria> alimentosCategorias = alicatDao.queryBuilder().where().eq("categoria_id",6).prepare();
				for (Object alimentoCategoria : alicatDao.query(alimentosCategorias).toArray()) {
					ids.add(((AlimentoCategoria) alimentoCategoria).getAlimento().getId());
				}
		    	PreparedQuery<Alimento> alimentosQuery = alimentoDao.queryBuilder().where().in("id", ids).prepare();
		    	alimentos=(ArrayList<Alimento>) alimentoDao.query(alimentosQuery);
			}
			else{
				alimentos= (ArrayList<Alimento>) alimentoDao.queryForAll();
			}
			return AlimentoParser.getInstance().fromModelToDTOArrayLazy(alimentos);
			
		} 
		catch (SQLException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	public ArrayList<AlimentoDTO> obtenerAlimentosCategoria(
			Context context, int idCategoria) {
		DatabaseHelper db =new DatabaseHelper(context);
		ArrayList<Alimento> alimentos=null;
		try {
			Dao<AlimentoCategoria, Integer> alicatDao = db.getAlimentoCategoriaDao();
			List<Integer>ids=new ArrayList<Integer>();
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");      
			Date hoy = sdf.parse(sdf.format(new Date()));
			GenericRawResults<String[]> rawResults = alicatDao.queryRaw("select * from consumos where "+ Consumo.FECHA_CONSUMO_FIELD_NAME +" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000)));
			List<String[]> results = rawResults.getResults();
			//Veo si existen consumos del dia la fecha
			if(!results.isEmpty()){
				//Esta queria toma los consumos del dia y los resta con la informacion nutricional del consumo del dia
				//Luego toma estos valores y los resta nutriente a nutriente por los de lo que costaria consumir una unidad de cada alimento
				//Por cada alimento que cada nutriente no sobrepase lo que se puede consumir se devuelve el id, siempre filtrando por categoria.
				rawResults = alicatDao.queryRaw("select alimento_nutriente.id_alimento "
																			+ "from (select regimen.nutriente_id,regimen.nombre,cantidad-consumido as cantConsu "
																			+ "from (select nutriente_id,nutrientes.nombre,compuestos.cantidad from (select * from regimenes_alimenticios where id=(select regimen_alimenticio_id from consumos_diarios ORDER BY id DESC LIMIT 1)) as regimen_alimenticio "
																			+ "inner join compuestos on compuestos.regimen_alimenticio_id=regimen_alimenticio.id "
																			+ "inner join nutrientes on nutrientes.id=compuestos.nutriente_id group by (compuestos.nutriente_id)) as regimen "
																			+ "inner join (select nutriente_id,nutrientes.nombre,sum(compuestos.cantidad * consumos.cantidad) as consumido from alimentos "
																			+ "inner join consumos on alimentos.id=consumos.alimento_id "
																			+ "inner join compuestos on compuestos.alimento_id=alimentos.id "
																			+ "inner join nutrientes on nutrientes.id=compuestos.nutriente_id where "+Consumo.FECHA_CONSUMO_FIELD_NAME+" BETWEEN "+hoy.getTime()+" AND "+(hoy.getTime()+ (1 * 24 * 60 * 60 * 1000))+" "
																			+ "group by (compuestos.nutriente_id)) as consumo on consumo.nutriente_id=regimen.nutriente_id) as puedo_consumir "
																			+ "inner join (select alimentos.id as id_alimento, nutriente_id, cantidad from alimentos "
																			+ "inner join compuestos on alimentos.id=compuestos.alimento_id inner join alimentos_categorias on alimentos.id=alimentos_categorias.alimento_id where alimentos_categorias.categoria_id= "+idCategoria+" order by compuestos.alimento_id, compuestos.nutriente_id) alimento_nutriente on alimento_nutriente.nutriente_id=puedo_consumir.nutriente_id "
																			+ "where  puedo_consumir.cantConsu- alimento_nutriente.cantidad>0 "
																			+ "group by alimento_nutriente.id_alimento having count(*)>4");
		    	results = rawResults.getResults();
		    	if(!results.isEmpty()){
					for (String[] strings : results) {
						ids.add(Integer.parseInt(strings[0]));
					}
		    	}
		    	if(idCategoria==6){
		    		/*Siempre muestro los Libres, aunque se pasen, justamente porque son "Libres"*/
			    	PreparedQuery<AlimentoCategoria> alimentosCategorias = alicatDao.queryBuilder().where().eq("categoria_id",6).prepare();
					for (Object alimentoCategoria : alicatDao.query(alimentosCategorias).toArray()) {
						ids.add(((AlimentoCategoria) alimentoCategoria).getAlimento().getId());
					}
		    	}
			}
			else{
				PreparedQuery<AlimentoCategoria> alimentosCategorias = alicatDao.queryBuilder().where().eq("categoria_id",idCategoria).prepare();
				for (Object alimentoCategoria : alicatDao.query(alimentosCategorias).toArray()) {
					ids.add(((AlimentoCategoria) alimentoCategoria).getAlimento().getId());
				}
			}
			Dao<Alimento, Integer> aliDao = db.getAlimentoDao();
			PreparedQuery<Alimento> alimentosQuery = aliDao.queryBuilder().where().in("id", ids).prepare();
			alimentos=(ArrayList<Alimento>) aliDao.query(alimentosQuery);
		} 
		catch (SQLException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return AlimentoParser.getInstance().fromModelToDTOArrayLazy(alimentos);
	}
	public ArrayList<AlimentoDTO> obtenerAlimentosIngesta(Context context) {
		
		DatabaseHelper db =new DatabaseHelper(context);
		ArrayList<AlimentoDTO> alimentos=new ArrayList<AlimentoDTO>();
		try {
				Dao<Alimento, Integer> alimentoDao = db.getAlimentoDao();
				alimentos= AlimentoParser.getInstance().fromModelToDTOArrayLazy((ArrayList<Alimento>) alimentoDao.queryBuilder().where().not().eq("nombre", "Liquido").query());
			} catch (SQLException e) {
				e.printStackTrace();
			}
		return alimentos;
	}
}